﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using Caliburn.Micro;

namespace NathansMapInfoProjects.PluginManager.Services
{
    public interface IFeedReader
    {
        /// <summary>
        /// Checks if this xml feed is vaild and can be used to provide plugins.  Override to provide own implementation.
        /// </summary>
        /// <returns></returns>
        bool IsFeedVaild();

        /// <summary>
        /// Returns the list of plugins from the feed.  Override to provide own implementation.
        /// </summary>
        /// <returns></returns>
        IEnumerable<PluginItem> GetPlugins();

        string FeedName { get; set; }
    }

    [Export(typeof(RepositoryService))]
    public class RepositoryService : IEnumerable<IFeedReader>
    {
        /// <summary>
        /// Opens a new <see cref="XmlFeedReader"/> for the supplied data.
        /// </summary>
        /// <param name="feedData">A string containing the data from a xml document.</param>
        /// <returns>A new <see cref="XmlFeedReader"/> that can return plugins from a feed.</returns>
        public IFeedReader GetReaderFor(string feedData)
        {
            var document = XDocument.Parse(feedData);
            return new XmlFeedReader(document);
        }

        public string GetDataFrom(string website)
        {
            HttpWebRequest wrq = (HttpWebRequest)HttpWebRequest.Create("http://www.musicalnerdery.com/component/option,com_rss/Itemid,0/feed,RSS2.0/no_html,1/");

            wrq.Proxy = WebProxy.GetDefaultProxy();
            wrq.Proxy.Credentials = CredentialCache.DefaultCredentials;

            StringBuilder oBuilder = new StringBuilder();
            StreamReader reder = new StreamReader(wrq.GetResponse().GetResponseStream());
            
            string data = reder.ReadToEnd();

            reder.Close();

            return data;
        }

        public IEnumerator<IFeedReader> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

    /// <summary>
    /// Reads the xml style feed and and returns a list of plugins in that feed.  
    /// </summary>
    public class XmlFeedReader : IFeedReader
    {
        static readonly ILog Log = LogManager.GetLog(typeof(XmlFeedReader));

        public XDocument FeedData { get; set; }

        public XmlFeedReader(XDocument feedData)
        {
            FeedData = feedData;
        }

        /// <summary>
        /// Checks if this xml feed is vaild and can be used to provide plugins.
        /// </summary>
        /// <returns></returns>
        public bool IsFeedVaild()
        {
            XmlSchemaSet schemas = new XmlSchemaSet();
            StreamReader reader = new StreamReader(@"Services\PluginFeed.xsd");
            schemas.Add("", XmlReader.Create(new StringReader(reader.ReadToEnd())));

            bool errors = false;
            this.FeedData.Validate(schemas, (o, e) =>
                                    {
                                        Log.Warn(String.Format("{0}", e.Message));
                                        errors = true;
                                    });
            return errors;
        }

        /// <summary>
        /// Returns the list of plugins from the feed.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<PluginItem> GetPlugins()
        {
            // Query the data and write out a subset of contacts
            var items = from c in this.FeedData.Descendants("mapinfo_plugin")
                        select new PluginItem
                        {
                            Name = (string)c.Attribute("name").Value,
                            Version = Convert.ToDecimal(c.Attribute("version").Value),
                            Description = (string)c.Element("description").Value,
                            Homepage = (string)c.Element("homepage").Value,
                            MapInfoVersions = (string)c.Element("mapinfo_versions").Value,
                            FileName = (string)c.Element("file_name").Value,
                            AuthorName = (string)c.Element("author_name").Value,
                            DownloadURL = (string)c.Element("download_url").Value
                        };

            return items;
        }

        public string FeedName { get; set;}
    }
}
